#include "stdafx.h"
#include <stdexcept>
#include <math.h>
#include "TestCase.h"
#include "TestResult.h"
#include "eString.h"
#include <typeinfo>
using namespace std;

namespace JHCPP{
	namespace CppUnit{
		CTestCase::CTestCase(const std::string& name): m_name (name)
		{
		}

		CTestCase::~CTestCase()
		{
		}

		void CTestCase::run(CTestResult *result)
		{
			result->startTest(this);

			setUp();
			try 
			{
				runTest();
			}
			catch (CCppUnitException& e) 
			{
				CCppUnitException* copy = new CCppUnitException(e);
				result->addFailure(this, copy);
			}
			catch (std::exception& e)
			{
				std::string msg(typeid(e).name());
				msg.append(": ");
				msg.append(e.what());
				result->addError(this, new CCppUnitException(msg));
			}
		#if !defined(_WIN32)
			catch (...)
			{
				CCppUnitException *e = new CCppUnitException ("unknown exception");
				result->addError (this, e);
			}
		#endif
			tearDown ();
			result->endTest(this);
		}

		CTestResult* CTestCase::run()
		{
			CTestResult* result = defaultResult();

			run(result);
			return result;
		}

		int CTestCase::countTestCases()
		{
			return 1; 
		}

		const std::string& CTestCase::name() const
		{
			return m_name; 
		}

		std::string CTestCase::toString()
		{
			const std::type_info& thisClass = typeid(*this); 
			return std::string(thisClass.name()) + "." + name(); 
		}

		void CTestCase::setUp()
		{
		}

		void CTestCase::tearDown()
		{
		}

		void CTestCase::runTest()
		{
		}

		CTestResult* CTestCase::defaultResult()
		{
			return new CTestResult;
		}

		void CTestCase::assertImplementation(bool condition, const std::string& conditionExpression, long lineNumber, const std::string& fileName)
		{
			if (!condition)
				throw CCppUnitException(conditionExpression, lineNumber, fileName);
		}

		void CTestCase::loop1assertImplementation(bool condition, const std::string& conditionExpression, long lineNumber, long data1lineNumber, const std::string& fileName)
		{
			if (!condition)
				throw CCppUnitException(conditionExpression, lineNumber, data1lineNumber, fileName);
		}

		void CTestCase::loop2assertImplementation(bool condition, const std::string& conditionExpression, long lineNumber, long data1lineNumber, long data2lineNumber, const std::string& fileName)
		{
			if (!condition)
				throw CCppUnitException(conditionExpression, lineNumber, data1lineNumber, data2lineNumber, fileName);
		}

		void CTestCase::assertEquals(long expected, long actual, long lineNumber, const std::string& fileName)
		{
			if (expected != actual)
				assertImplementation(false, notEqualsMessage(expected, actual), lineNumber, fileName);
		}

		void CTestCase::assertEquals(double expected, double actual, double delta, long lineNumber, const std::string& fileName)
		{
			if (fabs(expected - actual) > delta)
				assertImplementation(false, notEqualsMessage(expected, actual), lineNumber, fileName);
		}

		void CTestCase::assertEquals(const void* expected, const void* actual, long lineNumber, const std::string& fileName)
		{
			if (expected != actual)
				assertImplementation(false, notEqualsMessage(expected, actual), lineNumber, fileName);
		}

		void CTestCase::assertEquals(const std::string& expected, const std::string& actual, long lineNumber, const std::string& fileName)
		{
			if (expected != actual)
				assertImplementation(false, notEqualsMessage(expected, actual), lineNumber, fileName);
		}

		void CTestCase::assertNotNull(const void* pointer, const std::string& pointerExpression, long lineNumber, const std::string& fileName)
		{
			if (pointer == NULL)
				throw CCppUnitException(pointerExpression + " must not be NULL", lineNumber, fileName);
		}

		void CTestCase::assertNull(const void* pointer, const std::string& pointerExpression, long lineNumber, const std::string& fileName)
		{
			if (pointer != NULL)
				throw CCppUnitException(pointerExpression + " must be NULL", lineNumber, fileName);
		}

		void CTestCase::fail (const std::string& message, long lineNumber, const std::string& fileName)
		{
			throw CCppUnitException(std::string("fail: ") + message, lineNumber, fileName);
		}

		std::string CTestCase::notEqualsMessage(long expected, long actual)
		{
			return "expected: " + eString(expected) + " but was: " + eString(actual);
		}

		std::string CTestCase::notEqualsMessage(double expected, double actual)
		{
			return "expected: " + eString(expected) + " but was: " + eString(actual);
		}

		std::string CTestCase::notEqualsMessage(const void* expected, const void* actual)
		{
			return "expected: " + eString(expected) + " but was: " + eString(actual);
		}

		std::string CTestCase::notEqualsMessage(const std::string& expected, const std::string& actual)
		{
			return "expected: \"" + expected + "\" but was: \"" + actual + "\"";
		}

	}//end of namespace CppUnit
}//end of namespace JHCPP